// Copyright (c) 2019 Presto Labs Pte. Ltd.
// Author: donggu

use strum_macros::Display;

use crate::currency::Currency;
use crate::date::Date;
use crate::product::{ExpiryType, Product};

#[allow(dead_code)]
#[derive(Display)]
pub enum ExchangeEnum {
    Binance,
    Bitfinex,
    Bithumb,
    Bitmex,
    Bitstamp,
    Bittrex,
    Bybit,
    Coincheck,
    Coinone,
    Deribit,
    Fcoin,
    Gdax,
    Gopax,
    Hitbtc,
    Huobi,
    Korbit,
    Kraken,
    Okex,
    Prex,
    Quoinex,
    Upbit,
}

impl ExchangeEnum {
    fn exchange(&self) -> Box<dyn Exchange> {
        Box::new(match self {
            ExchangeEnum::Binance => Binance,
            ExchangeEnum::Bitfinex => Bitfinex,
            ExchangeEnum::Bithumb => Bithumb,
            ExchangeEnum::Bitmex => Bitmex,
            ExchangeEnum::Bitstamp => Bitstamp,
            ExchangeEnum::Bittrex => Bittrex,
            ExchangeEnum::Bybit => Bybit,
            ExchangeEnum::Coincheck => Coincheck,
            ExchangeEnum::Coinone => Coinone,
            ExchangeEnum::Deribit => Deribit,
            ExchangeEnum::Fcoin => Fcoin,
            ExchangeEnum::Gdax => Gdax,
            ExchangeEnum::Gopax => Gopax,
            ExchangeEnum::Hitbtc => Hitbtc,
            ExchangeEnum::Huobi => Huobi,
            ExchangeEnum::Korbit => Korbit,
            ExchangeEnum::Kraken => Kraken,
            ExchangeEnum::Okex => Okex,
            ExchangeEnum::Prex => Prex,
            ExchangeEnum::Quoinex => Quoinex,
            ExchangeEnum::Upbit => Upbit,
        })
    }
}

// TODO: replace this with macro.
pub struct Binance;
pub struct Bitfinex;
pub struct Bithumb;
pub struct Bitmex;
pub struct Bitstamp;
pub struct Bittrex;
pub struct Bybit;
pub struct Coincheck;
pub struct Coinone;
pub struct Deribit;
pub struct Fcoin;
pub struct Gdax;
pub struct Gopax;
pub struct Hitbtc;
pub struct Huobi;
pub struct Korbit;
pub struct Kraken;
pub struct Okex;
pub struct Prex;
pub struct Quoinex;
pub struct Upbit;

/// exchange information
pub trait Exchange {
    fn currency_list(&self) -> &'static [Currency];
    fn product_list(&self) -> &'static [Product];
    fn taker_fee(&self, price: f64) -> f64;
    fn maker_fee(&self, price: f64) -> f64;
    fn expiry_date(&self, expiry_type: ExpiryType, base_date: &Date) -> Date;
}

// impl Exchange for Binance {}
// impl Exchange for Bitfinex {}
// impl Exchange for Bithumb {}
// impl Exchange for Bitmex {}
// impl Exchange for Bitstamp {}
// impl Exchange for Bittrex {}
// impl Exchange for Bybit {}
// impl Exchange for Coincheck {}
// impl Exchange for Coinone {}
// impl Exchange for Deribit {}
// impl Exchange for Fcoin {}
// impl Exchange for Gdax {}
// impl Exchange for Gopax {}
// impl Exchange for Hitbtc {}
// impl Exchange for Huobi {}
// impl Exchange for Korbit {}
// impl Exchange for Kraken {}
// impl Exchange for Okex {}
// impl Exchange for Prex {}
// impl Exchange for Quoinex {}
// impl Exchange for Upbit {}
